package com.lingjtx.auth.controller;

import com.lingjtx.auth.vo.JsApiSignatureVo;
import com.lingjtx.common.core.ResponseResult;
import com.lingjtx.common.core.algorithm.SHA1;
import com.lingjtx.common.core.annotation.IgnoreLogin;
import com.lingjtx.common.core.constant.Const;
import com.lingjtx.common.core.constant.RedisConfig;
import com.lingjtx.common.core.handle.CallbackHandle;
import com.lingjtx.common.core.util.CommonUtil;
import com.lingjtx.common.core.util.DateTimeUtil;
import com.lingjtx.common.core.util.LinkGenerator;
import com.lingjtx.common.core.util.StringUtil;
import com.lingjtx.common.other.helper.DataCachePool;
import com.lingjtx.common.other.helper.WeiXinOauth;
import com.lingjtx.common.other.model.weixin.OauthResponse;
import com.lingjtx.common.other.model.weixin.WeiXinSignature;
import com.lingjtx.common.redis.service.IRedisService;
import com.lingjtx.common.security.model.LoginPo;
import com.lingjtx.common.thread.pooling.ObjectPoolTemplate;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import java.net.http.HttpClient;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Objects;
import java.util.UUID;

/**
 * 用户中心公共接口
 */
@Controller
public class WebController {

    @Value("${weixin.offiaccount.echostr:rT4uBaDXeCqzBmWnEzsWufnfCInBgB7_}")
    private String echostr;

    private final IRedisService redisService;
    private final ObjectPoolTemplate<HttpClient> httpObjectPoolTemplate;
    private final CallbackHandle callbackHandle;

    public WebController(IRedisService redisService,
                         @Qualifier("httpObjectPoolTemplate") ObjectPoolTemplate<HttpClient> httpObjectPoolTemplate,
                         @Qualifier("userServiceImpl") CallbackHandle callbackHandle) {
        this.redisService = redisService;
        this.httpObjectPoolTemplate = httpObjectPoolTemplate;
        this.callbackHandle = callbackHandle;
    }

    @IgnoreLogin
    @GetMapping(value = "/verify/mail_account/{key}", produces = "text/html")
    public String activateRestfulLink(@PathVariable("key") String key, Model model) {
        model.addAttribute("serverName", Const.SERVER_NAME);
        model.addAttribute("serverLogo", Const.SERVER_LOGO);
        if (LinkGenerator.valid(key, redisService)) {
            callbackHandle.process(key);
            return "active_success";
        }
        return "active_error";
    }

    @IgnoreLogin
    @GetMapping(value = "/verify/mail_account", produces = "text/html")
    public String activateLink(HttpServletRequest request, Model model) {
        model.addAttribute("serverName", Const.SERVER_NAME);
        model.addAttribute("serverLogo", Const.SERVER_LOGO);
        Enumeration<String> names = request.getParameterNames();
        if (names.hasMoreElements()) {
            String key = request.getParameter(names.nextElement());
            if (StringUtil.isNotEmpty(key)) {
                if (LinkGenerator.valid(key, redisService)) {
                    callbackHandle.process(key);
                    return "active_success";
                }
            }
        }
        return "active_error";
    }

    // 微信扫码绑定
    @IgnoreLogin
    @GetMapping(value = "/scan_bound_wx", produces = "text/html")
    public String scanBoundWx(HttpServletRequest request, Model model) {
        String id = request.getParameter(LinkGenerator.LinkType.IDENTITY.toString());
        // 微信回调的两个参数值
        String code = request.getParameter("code");
        String state = request.getParameter("state");

        if (StringUtil.isNotEmpty(id)) {
            if (StringUtil.isEmpty(code)) {
                // 先跳转微信登录授权
                String redirectUrl = Const.WEBURL + "/scan_bound_wx?identity=" + id;
                String url = WeiXinOauth.INSTANCE.getBaseWeixinOauthUrl(redirectUrl, redisService);
                return "redirect:" + url;
            }

            LoginPo entity = (LoginPo) LinkGenerator.getData(id, redisService);
            if (Objects.nonNull(entity) && LinkGenerator.valid(id, redisService)) {
                // 更改扫码状态为1：扫码状态：0-未扫码；1-已扫码；2-确认登录；3-二维码无效
                redisService.set(RedisConfig.KEY_SCANLOGIN_STATUS + entity.getQrcodeUid(), Const.ScanStatus.SCANED);
                OauthResponse oauthResponse = WeiXinOauth.INSTANCE.getOauthAccessToken(code, state, redisService, httpObjectPoolTemplate);
                if (Objects.nonNull(oauthResponse) && StringUtil.isNotEmpty(oauthResponse.getOpenid())) {
                    model.addAttribute("openid", oauthResponse.getOpenid());
                    model.addAttribute("token", entity.getIdentifier());
                    model.addAttribute("key", id);
                    model.addAttribute("baseUrl", Const.SERVER_URL);
                    return "weixin_scan_bound";
                }
            }
        }
        return "error";
    }

    // 扫码登录
    @IgnoreLogin
    @GetMapping(value = "/scan_login", produces = "text/html")
    public String scanLogin(HttpServletRequest request, Model model) {
        String id = request.getParameter(LinkGenerator.LinkType.IDENTITY.toString());
        String token = request.getParameter("token");

        if (StringUtil.isNotEmpty(id)) {
            if (StringUtil.isEmpty(token)) {
                // 先跳转微信登录授权
                String redirectUrl = Const.SERVER_URL + "/scan_login?identity=" + id;
                String url = WeiXinOauth.INSTANCE.getBaseWeixinOauthUrl(Const.WEBURL + "/login?cb=" + CommonUtil.specialUrlEncode(redirectUrl), redisService);
                return "redirect:" + url;
            }

            LoginPo entity = (LoginPo) LinkGenerator.getData(id, redisService);
            if (Objects.nonNull(entity) && LinkGenerator.valid(id, redisService)) {
                // 更改扫码状态为1：扫码状态：0-未扫码；1-已扫码；2-确认登录；3-二维码无效
                redisService.set(RedisConfig.KEY_SCANLOGIN_STATUS + entity.getQrcodeUid(), Const.ScanStatus.SCANED);

                model.addAttribute("token", token);
                model.addAttribute("key", id);
                model.addAttribute("baseUrl", Const.SERVER_URL);
                return "weixin_scan_login";
            }
        }
        return "error";
    }

    // 人脸登录：检测真人动作，验证人脸
    @IgnoreLogin
    @GetMapping(value = "/face_login", produces = "text/html")
    public String faceLogin(HttpServletRequest request, Model model) {
        model.addAttribute("baseUrl", Const.SERVER_URL);
        return "face_login";
    }

    @IgnoreLogin
    @ResponseBody
    @GetMapping("/weixin")
    public String verifyUrl(WeiXinSignature signature) {
        String[] array = new String[]{echostr, signature.getTimestamp(), signature.getNonce()};
        Arrays.sort(array);
        StringBuilder sb = new StringBuilder();
        for (String s : array) {
            sb.append(s);
        }
        String sign = SHA1.hexdigest(sb.toString());
        if (sign.equals(signature.getSignature())) {
            return signature.getEchostr();
        }
        return "weixin check signature error";
    }

    @IgnoreLogin
    @ResponseBody
    @GetMapping("/weixin/login/url")
    public ResponseResult<String> getWeiXinLoginUrl(String scope) {
        if (StringUtil.isNotEmpty(scope)) {
            return ResponseResult.createBySuccessToString(WeiXinOauth.INSTANCE.getWeixinOauthUrl(scope, Const.WEBURL + "/login", redisService));
        }
        return ResponseResult.createBySuccessToString(WeiXinOauth.INSTANCE.getUserinfoWeixinOauthUrl(redisService));
    }

    @IgnoreLogin
    @ResponseBody
    @GetMapping("/weixin/js_api_signature")
    public ResponseResult<JsApiSignatureVo> getJsApiSignature(String url) {
        String noncestr = UUID.randomUUID().toString();
        String timestamp = DateTimeUtil.getTimestamp();
        String jsapi_ticket = DataCachePool.INSTANCE.getTicket(redisService, httpObjectPoolTemplate);
        String param = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + noncestr +
                "&timestamp=" + timestamp +
                "&url=" + url;
        String signature = SHA1.hexdigest(param);
        JsApiSignatureVo jsApiSignatureVo = new JsApiSignatureVo();
        jsApiSignatureVo.setNonceStr(noncestr);
        jsApiSignatureVo.setTimestamp(timestamp);
        jsApiSignatureVo.setSignature(signature);
        return ResponseResult.createBySuccess(jsApiSignatureVo);
    }

}
